import requests
from lxml.etree import HTML


class Douban(object):
    def __init__(self):
        # 列表页url
        self.url = 'https://movie.douban.com/top250?start={}'
        # 总共有多少页
        self.max_page = 1
        # 请求头
        self.headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36'}
        # 详情页列表
        self.detail_list = []
        # 详情页信息列表
        self.info_list = []

    def get_html(self, url: str) -> str:
        """
        获取html源码
        :param url: 目标url
        :return: html源码
        """
        # 请求该url
        res = requests.get(url, headers=self.headers)
        # 返回html源码
        return res.text

    def get_detail_url(self, html: str) -> list:
        """
        获取详情页地址列表
        :param html: 要解析的html源码
        :return: 详情页列表
        """
        # 获取xpath对象
        tree = HTML(html)
        # 解析html获取当前页所有的详情页地址
        a_list = tree.xpath("//ol/li/div/div[@class='info']/div[1]/a/@href")
        return a_list

    def get_info(self, html: str) -> dict:
        """
        获取详情页信息
        :param html: 详情页html源码
        :return: 详情页信息
        """
        # 获取xpath对象
        tree = HTML(html)
        # 解析html获取电影名
        title = tree.xpath("//div[@id='content']/h1/span[1]/text()")[0]
        # 解析html获取导演名
        director = tree.xpath("//div[@id='info']/span[1]/span[2]/a/text()")[0]
        # 解析html获取所有的主演
        starring = '/'.join(tree.xpath("//div[@id='info']/span[3]/span[2]/a/text()"))
        # 返回信息
        return {'title': title, 'director': director, 'starring': starring}

    def save(self) -> None:
        """
        保存
        :return: None
        """
        """
        [
            {
                title: 电影名
                ....
            }
            ...
        ]
        """
        # 打开文件流
        with open("result.txt", 'w', encoding='utf-8') as f:
            # 将每部电影的详情字典循环出来
            for info in self.info_list:
                # 定义一个字符串
                res = ''
                # 将循环出来的电影的键值对循环出来
                for k, v in info.items():
                    # 拼接字符串
                    res += f"{k}: {v}\n"
                # 添加换行
                res += '\n'
                # 写入
                f.write(res)

    def main(self):
        # 循环出每一页的所有详情页地址
        for i in range(self.max_page):
            # 获取html源码
            html = self.get_html(self.url.format(i * 25))
            # 获取详情页地址
            self.detail_list += self.get_detail_url(html)
            print("第%d页详情列表获取完成" % (i + 1))
        # 循环出每一部电影的详情信息
        for index, url in enumerate(self.detail_list):
            # 获取html源码
            html = self.get_html(url)
            # 保存每一部电影的详情信息
            self.info_list.append(self.get_info(html))
            print("第%d部详情信息获取完成" % (index + 1))
        # 全部保存
        self.save()


if __name__ == '__main__':
    # 实例化对象
    douban = Douban()
    # 运行
    douban.main()
